It's my intention to document on this page the development of Gold Digger.

Concept

The concept for Gold Digger was the result of several different thoughts:

  1. Although I was proud of Skeleton, I realized gameplay quickly got repetitive. The way to avoid this is to have distinct levels, ideally of increasing difficulty.
  2. Lode Runner had been mentioned on the Stella mailing list as an ideal game for the SuperCharger, based on the possibility of having multiple loads.
  3. Since the SuperCharger is RAM based, it would be possible to use that RAM to create a virtual 2-D bitmap and/or object lookup table.
  4. Although it wouldn't be possible to create an in-game editor (how would you save), it would be feasible to make it possible for other people to create levels (and music).

So having decided on making a Lode Runner style game, the next step was to think through the basic gameplay and display kernel. So I thought back to the basic gameplay & object types I remembered from playing Lode Runner in highschool:

  1. You had to go running around, picking up gold, while avoiding the bad guys.
  2. You had the ability to dig through dirt (but not rock), although the holes would fill in over time. This could also be used to capture the bad guys (who would reappear at the top of the screen) and cause them to drop any gold they had picked up.
  3. In addition to the dirt,rock and gold, there were also ladders (for up and down), and ropes (across, but you couldn't dig while on a rope), and traps (which looked like dirt, but couldn't be dug, and you would fall through them).
  4. Some of the puzzles were strongly dependent upon the gameplay mechanics, e.g. you fell faster than the bad guys, how the bad guy's AI worked, etc.

As usual, searching Google located several fan sites, including several with graphics from the actual game. I learned that the original game used a 28x16 grid, and that I'd forgotten about the escape ladders which only appeared when you had picked up all of the gold on a level.

At this point I had been thinking about using a 32x32 grid drawn using playfield graphics. In order to fit the data into a single 256 byte page of memory, I would only have 4 object types: air, dirt, rock & ladders. This data would then have to be converted into a kind of bitmap which the kernel would then write to the playfield registers line by line.

I then realized two things:

  1. The conversion to playfield bitmap only needed to be done once per level.
  2. The object data wasn't required at all. I could store the level as a playfield bitmap, and manipulate that as required. Each object (including ropes) would just require scanning the bitmap. (Just like using POINT to create the logo, or the BIT instruction for the map in Skeleton.)

That being said, did I want to try to make an actual clone of Lode Runner? The answer came back no for the following reasons:

  1. Some of the levels in Lode Runner are strongly dependent on the gameplay mechanics. If I planned on using the levels from Lode Runner, I would need to duplicate those mechanics very closely. That would required a lot of work either testing & tweaking or disassembling & reverse engineering the original.
  2. The playfield bitmap would make traps and escape ladders more difficult. They would have to be stored separately. Though, I was thinking about using a similar storage to handle the holes.
  3. There is no way the 2600 could duplicate the graphics in Lode Runner exactly.
  4. With the playfield bitmap, I am restricted to 8 lines per row (so I can easily convert each object to a byte for gameplay processing). That would mean 24 rows for a 192 line NTSC screen. So with the 28x16 grid, I would have bunches of blank space onscreen. Ick!
  5. Some lawyer somewhere could easily decide that I was in mucho violation of someone's copyright, especially since I would be reusing and reverse-engineering so much.

First Kernel

That being decided, it was onto coding the first attempt at a kernel. The limitting factor, I knew, was going to be the time required to update the playfield registers every row; something I was now becoming experienced with.

But what about the player graphics? How was that going to work? Ideally, I wanted to re-use the player graphics multiple times to draw the player and robots. But in order to do that, I would have to come up with some way that I could strobe the RESPn registers in the middle of updating the PFn registers. Not easy.

In the end, I decided to initially not re-use the player graphics to start with in order to get the kernel going as quickly as possible. This would mean that the player and robots would flicker, but I could live with that for the moment. Later, I could revisit the challenge, get some help from the other 2600 programmers, and see if there was some way of accomplishing it. (Maybe using multiple kernels and jump tables.)

So I whipped together a simple kernel, created a simple level (based on the first two levels in Lode Runner), created a Basic program or two to change the text version of the level into the playfield bitmap, and ran it. It almost looked right, but there was a gap in the middle of the playfield, and the far left looked wrong. Hmm. Walking through a z26 trace revealed the problem - I was updating PF0 one cycle too late. Sigh. A modification to the kernel fixed the display, although not for all cases. Well, I knew I was going to have to re-work the kernel to handle overlapping player graphics anyway.

Music

When doing Skeleton, I wanted to have some music for the title screen. The actual piece I thought would be appropriate was March of the Trolls by Peter Grieg. (10 points if you know the reason why.) I even managed to track down a MIDI version, along with some apps which would print the MIDI codes out and an actual score. I had also started thinking through how I wanted to store the note info and the code to play it back.

But then I ran into the 4K limit when I added the static title and end screens. I knew I needed at least a 256 byte page to store the notes and that the PAL version of Skeleton would be even more space constrained due to the larger tables. So with a heavy heart, I filed the music idea for later.

During the concept stage I realized that it would be neat if other people could develop levels. Well, why not music too? Each level could have a unique musical theme. Not a problem since each level is being loaded fresh. No space problems!

When I was doing the music work for Skeleton, I spent a lot of time looking at the note table which Eckhard Stolberg had done. If I limitted myself to the "pure" waveforms, then sorted by frequency, I discovered that most of the scale was covered, with minimal overlap; plus the overlaps could be simply excluded.

The March of the Trolls provided another hint. Most of the music was either made up of quarter notes or 32nd notes. But there were some repeated quarter notes which would need a short rest or else they would turn into a single long note. The answer is to use a 32nd rest, which then changes the quarter note into a 3/32nd note. So three note lengths. 256/3 = 85r1, and there are 88 keys on a piano. Looking back at the sorted note table without overlaps shows that 85 values is enough (if the lowest frequency waveform is excluded).

The plan is for the music to be stored in a single 256 byte page, with one byte per note (up to 256 notes, which may end up being a little short; we'll see). A value of zero is used as a return to start, so the music doesn't have to be exactly 256 notes. Notes are retrieved sequentially, with both channels using the same table (though with different lengths, there may be some leapfrogging). Three user-specified note lengths (actually delays) and 85 frequencies. (Actually only 1-79 are specified. 80 is a rest with AUDVn=0. 81-85 will be a lookup for custom AUDCn and AUDFn values. Maybe percussion, or the excluded low notes.)

PAL vs NTSC

Creating both versions of a game can cause headaches.

  1. 192/262 versus 228/312 lines - do you simply add blank lines to fill out the screen, stretch (or squish) graphics or simply increase the playing area?
  2. 60Hz versus 50Hz - so delay counters need to be tweaked
  3. Audio frequency - is absolute pitch important, or is relative pitch okay?

Currently my plans are to take the easy way out and simply add blank lines to the PAL version and live with the slight frequency shift. However, since this is to be a SuperCharger game, there shouldn't be as big a deal with distributing multiple versions.

Sprites

The original Lode Runner used 5x10 pixel sprites (which I can't find anywhere!). One disadvantage of using the playfield registers is it makes the grid 4 pixels wide, and with a 32x32 grid, that means my sprites can only be 6 pixels high. Trying to get any detail in a 4x6 monochrome sprite is going to be tough. The only advantage is I will be able to use the full 8 pixel width to animate the dirt zapper. I might also cheat (especially if I can get my hands on the original sprites) and make some of the sprites a little wider than 4 pixels. I could also increase the height to 8 pixels, but I really like how some of the playfield icons look right now.

2002-11-20 Second Kernel

Finished typing in the second version of the kernel last night and the note lookup/translate subroutine. Just need to code the calling routine and add some initialization and I'll have music.

For the second kernel I did a paper cycle grid. Each line was numbered 0 - 75 for the clock cycle. I then noted when the playfield registers started & stopped (most in my cycle). Then I put in the PFn update routine from the first kernel, saw the mistake I made, and shifted everything by a cycle to correct it. Then I added the GRPn update to the top (both registers, in case both sprites are on the same line).

That left me with cycles 0-3 unused at the start of the line. Not enough cycles for the CPYs to turn on & off the GRPn updates. Hmm. Well, if I add the DEY & BNE ENDKERN to the end of the kernel, I have a bunch of cycles left over there. Okay, put in the CPYs there; I can JMP to that point once the VBLANK timer runs out. A STA WSYNC to put everything in sync (if I need the extra cycles, I can probably pull it out later) and a couple of NOPs to fill in the unused cycles at the start of the line, and bingo I'm back in business.

My current plan is to have 4 similar kernel structures; used depending on whether the player sprites overlap and which one is highest. This is done to keep the number of CPY/BRA cycles down.

This assumes that each frame I only draw two players. As I have said previously, the difficulty in displaying more than 2 players on each screen refresh is otherwise the kernel would have to strobe RESPn at the correct time in the middle of the PFn updates. (Note: since the grid width is 32, and each grid is one playfield pixel/bit, the 4 bits of the left PF0 are blank. Therefore any HMOVE lines will not show.) There are two ways of doing this:

  1. Create multiple versions of the kernel which would each be cycle counted to strobe RESP0 at the required cycle. However, the logic required to invoke these versions may be too complicated to squeeze into the kernel (especially since the 6502 doesn't have an indexed version of JMP).
  2. Add a blank line to each row on the screen which would be used exclusively to handle the RESP0. It still may be tricky to squeeze any required logic in. It would also impact the display, since every 7th or 9th line would be blank.

2002-11-21 Music?

Added the music calling routine. Of course it didn't work the first time, but a little tracing with Z26 (great tool, too bad the files are huge) and bingo! Hmm, that sounds mostly right. Gads that note is out of tune. And that sounds like a mistake. Guess more debugging is in order, though I probably won't be able to fix the out of tune notes. That's just the nature of 2600 music.

2002-11-22 More Music & Sprites

Had a look at the trace output. I thought for a while that I had a problem with my note calculations, but then I discovered that I had mistaken waveform for distortion in the freqform.txt file. Part of the problem is D2 is a quarter tone out of tune. I wonder if I could fix the problem by transposing the notes. Have to watch out for the notes the 2600 can't play though... Need to check my other notes for errors now.

It looks like the C-64 version of Lode Runner has the sprites in the file. Yea! Of course I will need to shrink them down to fit the grid size, but that's okay. It gives me a starting point at least. (My artwork skills suck, and trying to draw a 4x6 pixel stick figure is frustrating.)

2002-11-24 Sprites & skull sweat

Managed to extract the sprites from the C-64 version of Lode Runner. Unfortunately, it looks like they are more than 8 pixels wide and I can't find the second byte. Oh well. I'm not sure how usefull they will be. They look great onscreen, but on a pixel by pixel basis they don't look that good. It's like they suggest the figure rather than representing it. Wierd.

I also started thinking about how I'm going to do the actual non-kernel game logic. The real trick is to make it semi-efficient so it will fit in the time available. A big part of this is sprite manipulation along with the input & AI which cause the sprites to move. And since the screen is stored for efficient kernel display, it means a lot of bit scanning etc in order to figure out what each grid entry contains. Hmm, maybe a second lookup table wouldn't be a bad idea.

Something which I have decided is to change the size of the screen to 32x24. This makes each grid row 8 lines which should make some game logic simplier since it can mask to find out which row the sprite is on. This also makes the sprites taller, so it should be easier to draw something resembling a person. These sprites have to get done so I can put something on screen besides souped up playfield graphics.